package top.rish.converter.utils;

import top.rish.converter.info.AnnoWrap;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;

public class ObjKit {

    public static boolean isNumber(Object o) {
        return o instanceof Number;
    }

    public static boolean isNotEmpty(Object o) {
        return !isEmpty(o);
    }

    public static boolean isArray(Object o) {
        return  o != null && o.getClass().isArray();
    }

    public static boolean isEmpty(Object o) {
        if (o == null) {
            return true;
        } else if (isArray(o)) {
            Object[] oa = ((Object[]) o);
            return oa.length == 0;
        }else if (isIterator(o)) {
            return !((Iterator<?>) o).hasNext();
        } else if (o instanceof CharSequence) {
            return ((CharSequence) o).length() ==0;
        }else if(isIterable(o)) {
            return !((Iterable<?>) o).iterator().hasNext();
        } else if (isMap(o)) {
            return ((Map<?, ?>) o).isEmpty();
        } else {
            return false;
        }
    }

    public static <T> List<T> newEpmtyList(Class<T> c) {
        return  new ArrayList<>();
    }
    public static <T> Set<T> newEpmtySet(Class<T> c) {
        return  new HashSet<>();
    }

    public static <T> List<T> newArrayList(T... arr) {
        return  toList(arr);
    }

    public static <T> List<T> toList(T[] arr) {
        if(isEmpty(arr)){
            return new ArrayList<>();
        }
        return  Arrays.stream(arr).collect(Collectors.toList());
    }

    public static boolean isAllNotEmpty(Object... os) {
        if(ObjKit.isEmpty(os)){
            return false;
        }
        for (Object o : os) {
            if(ObjKit.isEmpty(o)){
                return false;
            }
        }
        return true;
    }



    public static boolean isTypeCollect(Object o) {
        return isIterator(o)
                || isIterable(o)
                || isArray(o);
    }

    public static boolean isIterator(Object o) {
        return o instanceof Iterator;
    }

    public static boolean isIterable(Object o) {
        return o instanceof Iterable;
    }


    public static boolean isMap(Object o) {
        return o instanceof Map;
    }

    public static boolean isAnnotation(Object o) {
        return  o instanceof Annotation;
    }

    public static boolean isEnum(Object o) {
        return  o instanceof Enum;
    }

    public static boolean equal(Object v1, Object v2) {
        return Objects.equals(v1,v2);
    }

    public static Set<Field> toSet(Field[] arr) {
        if(isEmpty(arr)){
            return new HashSet<>();
        }
        return  Arrays.stream(arr).collect(Collectors.toSet());
    }


    @FunctionalInterface
    public interface AnyNumFunc<P, R> {
        R execute(P v);
    }

    public static boolean isInt(Object o) {
        return isAnyNumType(o, Integer::parseInt);
    }

    public static boolean isStr(Object o) {
        return o instanceof String;
    }

    public static Boolean isDouble(Object o) {
        return isAnyNumType(o, Double::parseDouble);
    }

    private static <T> boolean isAnyNumType(Object o, AnyNumFunc<String, T> c) {
        if (!isNumber(o)) {
            return false;
        }
        try {
            return c.execute(Objects.toString(o)) != null;
        } catch (Exception e) {
            return false;
        }
    }

    public static boolean isLong(Object o) {
        return isAnyNumType(o, Long::parseLong);
    }

}
